use record::*;
use regex::Regex;
use std::fs::{read, File};
use std::io::prelude::*;
use std::io::BufReader;
use std::io::Error;
use std::io::ErrorKind;
use std::{collections::HashMap, path::PathBuf};

pub mod record;

pub struct FormatParser {
    // 文件名
    filename: String,

    // 存放 loop 变量
    pub loop_map: HashMap<String, u64>,
    pub struct_map: HashMap<String, Record>,
    pub dict_map: HashMap<String, Record>,

    // 标志着后续的记录会写入到一个Struct或者Dict中
    composed_flag: bool,
    tmp_composed_record: Record,
    // tmp_record_vec : Vec<Record>,
}

impl FormatParser {
    pub fn new() -> FormatParser {
        FormatParser {
            filename: String::from(""),
            loop_map: HashMap::new(),
            struct_map: HashMap::new(),
            dict_map: HashMap::new(),
            composed_flag: false,
            tmp_composed_record: Record::new(),
        }
    }

    pub fn set_fmt_file(&mut self, filename: &PathBuf) -> bool {
        self.filename = filename.to_string_lossy().trim().to_string();
        true
    }

    fn join_paths(&self, filename: &String, inc_filename: &str) -> PathBuf {
        let mut full_path = PathBuf::new();
        let mut tmp_filename = String::new();

        // 如果 filename 不是以路径分隔符开始的，我们假设它是一个相对路径
        // 并将它与当前目录（.）连接起来，以确保正确地构建路径。
        if !filename.starts_with('/') && !filename.starts_with('.') {
            tmp_filename = format!("./{}", filename);
        } else {
            tmp_filename = filename.clone();
        }

        // 将 filename 转换为 PathBuf，并尝试将其分解为目录和文件名。
        let mut filename_path = PathBuf::from(tmp_filename);
        let file_name = filename_path
            .file_name()
            .map(|os_str| os_str.to_os_string())
            .unwrap_or_default();

        // 清除 filename 中的文件名部分，只保留路径。
        filename_path.pop();

        // 将路径和文件名添加到 full_path 中。
        full_path.extend(&filename_path);
        full_path.push(inc_filename);

        full_path
    }

    fn get_inc_file_content(
        &mut self,
        all_records: &mut Record,
        line: &String,
    ) -> Result<String, std::io::Error> {
        if let Some(start) = line.find('"') {
            if let Some(end) = line[start + 1..].find('"') {
                let inc_filename = &line[start + 1..start + 1 + end];
                println!("self.filename is {}", self.filename);
                println!("inc_filename is {}", inc_filename);
                let ifile = self.join_paths(&self.filename, inc_filename);
                println!("ifile is {}", ifile.to_string_lossy());
                // 打开文件
                let file = File::open(&ifile)?;
                // 创建一个缓冲读取器
                let reader = BufReader::new(file);
                let proc_res = self.process_file_to_records(all_records, reader);
                return Ok(inc_filename.to_string());
            }
        }
        return Err(Error::new(
            ErrorKind::Other,
            "#include后面没有找到文件名".to_string(),
        ));
    }

    fn process_file_to_records(
        &mut self,
        all_records: &mut Record,
        reader: BufReader<File>,
    ) -> Result<(), std::io::Error> {
        for line in reader.lines() {
            // line 是一个 Result<String, io::Error> 类型
            let line = line?;
            if line.trim().starts_with("#include") {
                // 处理包含关系
                let inc_file = self.get_inc_file_content(all_records, &line);
                if let Err(inc_err) = inc_file {
                    return Err(Error::new(
                        ErrorKind::Other,
                        "err-get_inc_file_content".to_string(),
                    ));
                }
            }

            let pline = self.parse_line(&line);
            match pline {
                Ok(rec) => {
                    println!("          OK: name:{}; date_type:{:?}; length:{}; description:{}; veclength:{}", rec.name, rec.date_type, rec.length, rec.description, rec.record_vec.len());
                    if rec.record_vec.len() > 0 {
                        for (index, value) in rec.record_vec.iter().enumerate() {
                            println!("              {} OK: name:{}; date_type:{:?}; length:{}; description:{}", index, value.name, value.date_type, value.length, value.description);
                        }
                    }
                    all_records.record_vec.push(rec);
                }
                Err(fmt_err) => match fmt_err {
                    FmtParseError::MyInfo(info) => {
                        println!(" WARN{}", info);
                    }
                    FmtParseError::MyError(err) => {
                        println!("ERROR{}", err);
                        return Err(Error::new(ErrorKind::Other, err));
                    }
                },
            }
        }
        Ok(())
    }

    pub fn parse(&mut self) -> Result<Record, std::io::Error> {
        // 打开文件
        let file = File::open(&self.filename)?;
        // 创建一个缓冲读取器
        let reader = BufReader::new(file);
        let mut all_records = Record::new();

        let proc_res = self.process_file_to_records(&mut all_records, reader);

        Ok(all_records)
    }

    fn parse_line(&mut self, line: &String) -> Result<Record, FmtParseError> {
        let line_trim_all = self.trim_comment_blank(line);

        if line_trim_all.len() == 0 {
            return Err(FmtParseError::MyInfo(
                "这一行无语句，不用解析。".to_string(),
            ));
        }

        println!("{}", line_trim_all);
        if line_trim_all.starts_with("{") {
            if self.composed_flag == true {
                return Err(FmtParseError::MyError(
                    "重复的 左边大括号 。不可嵌套定义！".to_string(),
                ));
            } else {
                if line_trim_all.trim().len() == 1 {
                    self.composed_flag = true;
                    return Err(FmtParseError::MyInfo(
                        "单独一个 左大括号，定义结构体或者枚举开始".to_string(),
                    ));
                }
            }
        } else if line_trim_all.starts_with("}") {
            if self.composed_flag == false {
                return Err(FmtParseError::MyError("缺少 左边大括号 定义！".to_string()));
            } else {
                if line_trim_all.trim().len() == 1 {
                    return Err(FmtParseError::MyError(
                        "单独一个 右大括号，后面应该定义Dict或者Struct。".to_string(),
                    ));
                }
            }
        }

        // 尝试解析出 record 来
        let record = self.extract_record(&line_trim_all);
        if let Ok(rec) = record {
            match rec.date_type {
                RecordType::_InnerCustomStruct => {
                    if self.tmp_composed_record.record_vec.len() > 0 {
                        self.tmp_composed_record.name = rec.name;
                        self.tmp_composed_record.date_type = RecordType::_InnerCustomStruct;
                        self.composed_flag = false;
                        self.struct_map.insert(
                            self.tmp_composed_record.name.clone(),
                            self.tmp_composed_record.clone(),
                        );
                        self.tmp_composed_record = Record::new();
                    } else {
                        self.struct_map.insert(rec.name.clone(), rec);
                    }
                    return Err(FmtParseError::MyInfo(
                        "进入 struct_map 结构体中".to_string(),
                    ));
                }
                RecordType::_InnerCustomDictionary => {
                    if self.tmp_composed_record.record_vec.len() > 0 {
                        self.tmp_composed_record.name = rec.name.clone();
                        self.tmp_composed_record.date_type = RecordType::CustomDictionary(rec.name);
                        self.tmp_composed_record.length = rec.length;
                        self.composed_flag = false;
                        self.dict_map.insert(
                            self.tmp_composed_record.name.clone(),
                            self.tmp_composed_record.clone(),
                        );
                        self.tmp_composed_record = Record::new();
                    } else {
                        self.dict_map.insert(rec.name.clone(), rec);
                    }

                    return Err(FmtParseError::MyInfo("进入 dict_map 结构体中".to_string()));
                }
                _ => {
                    if self.composed_flag == true {
                        self.tmp_composed_record.record_vec.push(rec);
                        return Err(FmtParseError::MyInfo("进入暂存的结构体中".to_string()));
                    }
                    Ok(rec)
                }
            }
        } else {
            record
        }
    }

    // 去除注释和注释边上的空格
    fn trim_comment_blank(&self, line: &String) -> String {
        if let Some(index) = line.find("//") {
            let trimed_line = &line[..index];
            let trimed_line = trimed_line.trim();
            return trimed_line.to_string();
        }

        return line.clone();
    }

    fn get_signed_endian(&self, type_attr: &str) -> (bool, bool) {
        let signed = type_attr.contains("s");
        let endian = type_attr.contains("le");
        (signed, endian)
    }

    /**
     * 返回 (字段个数，字段标题，类型名称，重复个数，注释描述)
     */
    fn get_record_parts(&self, record_content: &str) -> (usize, String, RecordType, u32, String) {
        let mut field_name = String::new();
        let mut full_type_name = String::new();
        let mut repeat_times = 0;
        let mut description = String::new();

        let parts: Vec<&str> = record_content.split("|").collect();

        // for (index, part) in parts.iter().enumerate() {
        //     println!("部分 {}: {}", index, part);
        // }

        if parts.len() == 4 {
            let field3 = parts.get(3).unwrap();
            description = String::from((*field3).trim());
        }

        if parts.len() >= 3 {
            let field2 = parts.get(2).unwrap();
            if let Ok(number) = field2.parse::<u32>() {
                repeat_times = number;
            } else {
                println!("无法将 {} 转换成数字", field2);
                return (0, String::new(), RecordType::None, 0, String::new());
            }
        }

        if parts.len() >= 2 {
            let field1 = parts.get(1).unwrap();
            full_type_name = String::from((*field1).trim()).to_lowercase();
        }

        if parts.len() >= 1 {
            let field0 = parts.get(0).unwrap();
            field_name = String::from((*field0).trim());
        }

        let re_type = Regex::new(r"^(\w*)(\((.*)\))?").unwrap();
        let (type_name, type_attr) = if let Some(captures) = re_type.captures(&full_type_name) {
            let type_name = captures.get(1).map_or("", |m| m.as_str()).to_string();
            let type_attr = captures.get(3).map_or("", |m| m.as_str()).to_string();
            (type_name, type_attr)
        } else {
            (full_type_name.to_string(), String::new())
        };

        let signed_endian = self.get_signed_endian(&type_attr);
        let rec_type = match type_name.as_str() {
            "byte" => RecordType::Byte(signed_endian.0, signed_endian.1),
            "word" => RecordType::Word(signed_endian.0, signed_endian.1),
            "long" => RecordType::Long(signed_endian.0, signed_endian.1),
            "bcd" => RecordType::Bcd,
            "hex" => RecordType::Hex,
            "hexstring" => RecordType::HexString,
            "block" => RecordType::Block,
            "char" => RecordType::Char(type_attr),
            "date" => RecordType::Date,
            "time" => RecordType::Time,
            "timestamp" => RecordType::Timestamp,
            _ => {
                if self.struct_map.contains_key(&type_name) {
                    RecordType::CustomStruct(type_name)
                } else if self.dict_map.contains_key(&type_name) {
                    RecordType::CustomDictionary(type_name)
                } else {
                    RecordType::None
                }
            }
        };

        (parts.len(), field_name, rec_type, repeat_times, description)
    }

    // 获取一个记录中各个字段的值
    fn extract_record(&mut self, line: &String) -> Result<Record, FmtParseError> {
        let mut record_contents = String::new();
        let mut struct_name = String::new();
        let mut loop_def_name = String::new();
        let mut loop_using_name = String::new();
        // 样例有下面几种：
        // 1） 单字节0|Byte|0
        // 2） 双字节1|WORd|1|
        // 3） 单字节2|Byte|4|长度为4表示这个字段占用4Byte
        // 4） } => struct:my_type
        // 5） {二进制数据块|Hex|16|16个字节的HEX数据块，不会被解析成字符  } => struct:my_binary
        // 6） ASCII长度|Byte|1|长度注释 => loop:cnt
        // 7） 字符串3|Char(UTF-8)|60|按照UTF-8编码解析 <= loop:cnt
        // 8） 0x10 => Mifare Ultralight    // dictionary的条目
        // 9） } => dict:DictChipType(Byte|1) // 字典，占用1个字节
        // 解析返回一个 struct 类型
        let re_braces = Regex::new(r"\{(.*?)\}").unwrap(); // 匹配 5） {二进制数据块|Hex|16|16个字节的HEX数据块，不会被解析成字符  }
        let re_struct = Regex::new(r"^}\s*=>\s*struct\s*:\s*(\w+)").unwrap(); // 匹配 4） } => struct:my_type
        let re_loop_def = Regex::new(r"(.*?)\s*=>\s*loop\s*:\s*(\w+)").unwrap(); // 匹配 6） ASCII长度|Byte|1|长度注释 => loop:cnt
        let re_loop_using = Regex::new(r"(.*?)\s*<=\s*loop\s*:\s*(\w+)").unwrap(); // 匹配 7） 字符串3|Char(UTF-8)|60|按照UTF-8编码解析 <= loop:cnt
        let re_dictionary_item = Regex::new(r"\s*(.*?)\s*=>\s*(.*$)").unwrap(); // 匹配 8） 0x10 => Mifare Ultralight    // dictionary的条目
        let re_dictionary = Regex::new(r"^}\s*=>\s*dict\s*:\s*(\w+)\((\d+)\)").unwrap(); // 匹配 9） } => dict:DictChipType(1) // 字典，在原文件中实际占用的1个字节
                                                                                         //// 匹配 5）
        if let Some(captures) = re_braces.captures(line) {
            let content_in_braces = captures.get(1).unwrap().as_str().trim();
            if content_in_braces.len() > 0 {
                record_contents = content_in_braces.to_string();
            }

            // println!("大括号中的内容是 {}", content_in_braces);
            let re_struct = Regex::new(r"=>\s*struct\s*:\s*(\w+)").unwrap();
            if let Some(captures) = re_struct.captures(line) {
                let sname = captures.get(1).map_or("", |m| m.as_str());
                if sname.len() > 0 {
                    struct_name = sname.to_string();
                }
            } else {
                return Err(FmtParseError::MyError(
                    "没有匹配到结构体名称，必须要有!".to_string(),
                ));
            }
        //// 匹配 4）
        } else if let Some(captures) = re_struct.captures(line) {
            let sname = captures.get(1).map_or("", |m| m.as_str());
            if sname.len() > 0 {
                struct_name = sname.to_string();

                // 没有记录，只要 struct 名字，那么这儿就返回了
                let mut stt_rec = Record::new();
                stt_rec.name = struct_name.to_lowercase();
                stt_rec.date_type = RecordType::_InnerCustomStruct;
                return Ok(stt_rec);
            }
        } else if let Some(captures) = re_loop_def.captures(line) {
            let content_in_braces = captures.get(1).unwrap().as_str().trim();
            if content_in_braces.len() > 0 {
                record_contents = content_in_braces.to_string();
                println!("record_contents is {}", record_contents)
            }

            let lname = captures.get(2).unwrap().as_str().trim();
            if lname.len() > 0 {
                loop_def_name = lname.to_string();
                println!("loop_def_name is {}", loop_def_name)
            }
        } else if let Some(captures) = re_loop_using.captures(line) {
            let content_in_braces = captures.get(1).unwrap().as_str().trim();
            if content_in_braces.len() > 0 {
                record_contents = content_in_braces.to_string();
                println!("record_contents is {}", record_contents)
            }

            let lname = captures.get(2).unwrap().as_str().trim();
            if lname.len() > 0 {
                loop_using_name = lname.to_string();
                println!("loop_using_name is {}", loop_using_name)
            }
        } else if let Some(captures) = re_dictionary.captures(line) {
            let dname = captures.get(1).map_or("", |m| m.as_str());
            if dname.len() == 0 {
                return Err(FmtParseError::MyError("字典名字为空".to_string()));
            }

            // let item_type = captures.get(2).map_or("", |m| m.as_str());
            // if item_type.len() == 0 {
            //     return Err(FmtParseError::MyError("字典属性，类型为空".to_string()));
            // }

            let item_len = captures.get(2).map_or("", |m| m.as_str());
            if item_len.len() == 0 {
                return Err(FmtParseError::MyError("字典属性，长度为空".to_string()));
            }

            // let mut typ = RecordType::None;
            let mut len = 1;
            if let Ok(ll) = item_len.parse::<u32>() {
                len = ll;
            } else {
                println!("转换出错了 {}", item_len);
                return Err(FmtParseError::MyError("转换出错了!".to_string()));
            }

            let mut dict_rec = Record::new();
            dict_rec.name = dname.to_lowercase();
            dict_rec.date_type = RecordType::_InnerCustomDictionary;
            dict_rec.length = len;
            return Ok(dict_rec);
        } else if let Some(captures) = re_dictionary_item.captures(line) {
            let dict_item = captures.get(1).unwrap().as_str().trim();
            if dict_item.contains("|") || dict_item.contains("}") {
                println!("dictionary_item error {}", dict_item);
                return Err(FmtParseError::MyError("字典解析出错了!".to_string()));
            }
            if dict_item.len() > 0 {
                let item_description = captures.get(2).unwrap().as_str().trim();
                let mut rec = Record::new();
                rec.name = dict_item.to_lowercase();
                rec.date_type = RecordType::Word(false, false);
                rec.length = 0; // 实际解析时使用 dict 名字下的rec.length
                                // rec.length   需要再dict::xxx(1)之后才能解析出来
                rec.description = item_description.to_string();
                return Ok(rec);
            } else {
                return Err(FmtParseError::MyError("字典解析出错：空!".to_string()));
            }
        }

        if record_contents.len() == 0 && struct_name.len() == 0 {
            // 1）~3） 的场景
            record_contents = line.clone();
        }

        let parts = self.get_record_parts(&record_contents);
        let mut rec = Record::new();

        rec.name = parts.1.to_lowercase();
        rec.date_type = parts.2;
        rec.length = parts.3;
        if parts.0 == 4 {
            rec.description = parts.4;
        }

        if struct_name.len() > 0 {
            let mut stt_rec = Record::new();
            stt_rec.name = struct_name.to_lowercase();
            stt_rec.date_type = RecordType::_InnerCustomStruct;
            stt_rec.record_vec.push(rec);
            return Ok(stt_rec);
        } else if loop_def_name.len() > 0 {
            rec.loop_counter_name = loop_def_name.clone();
            rec.loop_counter_define = true;
            rec.loop_counter_using = false;
            if self.loop_map.contains_key(&loop_def_name) {
                let msg = format!("loop变量{}已经定义，请用其他名字。", loop_def_name);
                return Err(FmtParseError::MyError(msg));
            }
            self.loop_map.insert(loop_def_name, 0);
        } else if loop_using_name.len() > 0 {
            rec.loop_counter_name = loop_using_name.clone();
            rec.loop_counter_define = false;
            rec.loop_counter_using = true;

            if self.loop_map.contains_key(&loop_using_name) {
                let msg = format!("loop变量{}已匹配", loop_using_name);
            } else {
                let msg = format!("loop变量{}未定义，请检查其名字是否正确", loop_using_name);
                return Err(FmtParseError::MyError(msg));
            }
        }

        return Ok(rec);
    }
}

#[cfg(test)]
mod tests {
    use super::*; // 导入当前模块的内容

    #[test]
    fn test_trim_comment_blank_1() {
        let fp = FormatParser::new();
        let line = String::from("  //  	  你好    中间 mid  have blank     .     ");
        assert_eq!("", &fp.trim_comment_blank(&line));
    }
}
